#-*- coding:utf-8 -*-
from datetime import datetime
import time
import urllib, urllib2
import json
import re
import os
import kaptan
config = kaptan.Kaptan(handler="file")
config.import_config('config')
DEBUG = os.getenv('NUIDEBUG')
month = {'Jan': '01', 'Feb': '02', 'Mar': '03', 'Apr': '04', 'May': '05', 'Jun': '06', 'Jul': '07', 'Aug': '08', 'Sep': '09', 'Oct': '10', 'Nov': '11', 'Dec': '12'}

class NLog:
    def __init__(self):
        self.ip = ''
        self.time = ''
        self.method = ''
        self.target = ''
        self.status = ''
        self.referer = ''
        self.ua = ''

    # def is_4xx(self):
    #     if self.status.startswith('4'):
    #         return True
    #     return False

    def is_ghost(self):
        """ unrecognized log """
        if self.method in ('GET', 'POST', 'PUT', 'PATCH', 'HEAD', 'OPTIONS', 'CONNECT'):
            return False
        return True

    def is_valid(self):
        if self.is_blacklist():
            return False
        return True

    def is_blacklist(self):
        if config.get('ip_bl'):
            for i in config.get('ip_bl'):
                if self.ip.startswith(i):
                    return True

        if config.get('target_bl'):
            for i in config.get('target_bl'):
                if re.search(i, self.target):
                    return True

        return False

    def output(self):
        print """
        ip: {0}
        time: {1}
        method: {2}
        target: {3}
        referer: {4}
        ua: {5}
        """.format(self.ip, self.time, self.method, self.target, self.status, self.referer, self.ua)

class ND:
    """Nginx Data"""
    def __init__(self, file):
        self.start_day = self.end_day = 0
        self.ip_dict = {}
        self.time_dict = {}
        self.status_dict = {}
        self.target_dict = {}
        self.referer_dict = {}
        self.ghost_dict = {}
        self.logs = []

        print 'Parse log file: %s ' % file
        self.parse(file=file)

    def parse(self, file):
        self.start = datetime.now()
        print datetime.now()
        with open(file) as f:
            print 'Success open file...'

            for line in f :
                log = NLog()
                line_arr = line.split()
                assert len(line_arr) >= 10

                log.ip = line_arr[0] # ip

                left = right = 0
                for i in range(3):
                    left = line.index('"', right + 1)
                    right = line.index('"', left + 1)
                    if i == 0:
                        request = line[left+1:right+5]
                        data = request.split('"')
                        log.status = data[1].strip()
                        arr = data[0].split()
                        if len(arr) == 3:
                            (log.method, log.target, version) = arr # method, target, status
                        else:
                            log.method = data[0]
                    if i == 1:
                        log.referer = line[left+1:right] # referer
                    if i == 2:
                        log.user_agent = line[left+1:right] # ua

                pattern = re.compile(r'([\d]+)/([\w]+)/([\d]+):(.*)')
                m = pattern.match(line_arr[3][1:])

                day = int(month[m.group(2)]) * 30 +  int(m.group(1))
                if self.start_day == 0 :
                    self.start_day = day
                self.end_day = day
                log.time = '{0}-{1}-{2} {3}'.format(m.group(3), month[m.group(2)], m.group(1), m.group(4)) # time

                if log.is_valid():
                    # log.output()
                    self.logs.append(log)

        self.end = datetime.now()
        t = self.end - self.start
        print 'log count: {0} DIFF time  {1}.{2}:'.format(len(self.logs), t.seconds, t.microseconds)

    def query(self):
        if DEBUG: print 'start query : ', datetime.now()
        for log in self.logs:
            self.ip_dict[log.ip] = self.ip_dict[log.ip] + 1 if self.ip_dict.has_key(log.ip) else 1

            days  = 0 if self.start_day == self.end_day else 1
            log.time = log.time.split()[0] if days else log.time.split()[1][:5]

            self.time_dict[log.time] = self.time_dict[log.time] + 1 if self.time_dict.has_key(log.time) else 1
            if not log.is_ghost():
                target = '{0} {1} {2}'.format(log.method, log.target, log.status)
                self.target_dict[target] = self.target_dict[target] + 1 if self.target_dict.has_key(target) else 1

            self.status_dict[log.status] = self.status_dict[log.status] + 1 if self.status_dict.has_key(log.status) else 1
            if log.referer != '-':
                self.referer_dict[log.referer] = self.referer_dict[log.referer] + 1 if self.referer_dict.has_key(log.referer) else 1

            if log.is_ghost():
                ghost = '{0} {1}'.format(log.method, log.status)
                self.ghost_dict[ghost] = self.ghost_dict[ghost] + 1 if self.ghost_dict.has_key(ghost) else 1

        result = (sort(self.ip_dict),
                sorted(self.time_dict.iteritems()), # 默认按 key 排序
                sort(self.target_dict),
                sort(self.status_dict),
                sort(self.referer_dict),
                sort(self.ghost_dict))

        if DEBUG: print 'end query : ', datetime.now()
        return result

def sort(dict, index=400):
    return sorted(dict.iteritems(), key=lambda v:v[1], reverse=True)[:index]


